package cs342.project1.mathNotebook.tests.notebook;

import static org.junit.Assert.*;
import junit.framework.Assert;

import org.junit.Test;

import cs342.project1.mathNotebook.data.Parser;
import cs342.project1.mathNotebook.expressions.*;
import cs342.project1.mathNotebook.notebook.NotebookEntry;

public class NotebookEntryTests {
	private final double delta = 0.1;
	
	/**
	 * Verifies the area calculation works for a simple function
	 */
	@Test
	public void testCalculateArea() {
		NotebookEntry entry = new NotebookEntry();
		entry.functionString = "2x";
		entry.function = new MultExpr(new LiteralExpr(2.0), new VarExpr("x"));
		entry.minXCoordinate = 5.0;
		entry.maxXCoordinate = 15.0;
		
		double result = entry.calculateArea();
		
		Assert.assertEquals("Area must match the expected result", 200.0, result, delta);
	}
	
	/**
	 * Tests a function that approaches infinity gives an infinite area.
	 * This should not crash
	 */
	@Test
	public void testAsymptote() {
	    NotebookEntry entry = new NotebookEntry();
	    entry.functionString = "1/x";
	    entry.function = new DivExpr(new LiteralExpr(1.0), new VarExpr("x"));
	    entry.minXCoordinate = 0.0;
	    entry.maxXCoordinate = 10.0;
	    
	    double result = entry.calculateArea();
	    
	    Assert.assertEquals("area must match the expected result", Double.POSITIVE_INFINITY, result, delta);
	}
	
	/**
	 * Verifies that area can be calculated for a function that drops below
	 * Y=0.
	 */
	@Test
	public void testGraphThatDropsBelowYEqualsZero() {
		NotebookEntry entry = new NotebookEntry();
		entry.functionString = "x^2-4";
		entry.function = new SubExpr(new PowExpr(new VarExpr("x"), new LiteralExpr(2.0)), new LiteralExpr(4.0));
		entry.minXCoordinate = -25;
		entry.maxXCoordinate = 25;
		
		double result = entry.calculateArea();
		
		Assert.assertEquals("Area must match the expected result", 10216.6666667, result, delta);
	}
	
	/**
	 * Verifies area calculation of x^3
	 * @throws Exception 
	 */
	@Test
	public void testXCubed() throws Exception {
		NotebookEntry entry = new NotebookEntry();
		entry.functionString = "x^3";
		entry.function = new PowExpr(new VarExpr("x"), new LiteralExpr(3.0));
		entry.minXCoordinate = 0;
		entry.maxXCoordinate = 10;
		
		double result = entry.calculateArea();
		
		Assert.assertEquals("Area must match the expected result", 2500.0, result, delta);
	}
	
	/**
	 * Verifies the area calculation of x^3 + 12
	 */
	@Test
	public void testXCubedPlusTwelve() {
		NotebookEntry entry = new NotebookEntry();
		entry.functionString = "x^3 + 12";
		entry.function = new AddExpr(new PowExpr(new VarExpr("x"), new LiteralExpr(3.0)), new LiteralExpr(12.0));
		entry.minXCoordinate = -2;
		entry.maxXCoordinate = 10;
		
		double result = entry.calculateArea();
		
		Assert.assertEquals("Area must match the expected result", 2640.0, result, delta);
	}
	
	/**
	 * Verifies the area calculation of x^4+3x
	 */
	@Test
	public void testXToTheFourthPlusThreeX() {
		NotebookEntry entry = new NotebookEntry();
		entry.functionString = "x^4 + 3*x";
		entry.function = new AddExpr(new PowExpr(new VarExpr("x"), new LiteralExpr(4.0)), new MultExpr(new LiteralExpr(3.0), new VarExpr("x")));
		entry.minXCoordinate = -4;
		entry.maxXCoordinate = 9;
		
		double result = entry.calculateArea();
		
		Assert.assertEquals("Area must match the expected result", 12112.1, result, delta);
	}
}
